import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JComponent;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.ActionListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.Calendar;

public class GraphPane extends JTabbedPane implements ActionListener, ChangeListener
{
	private DateList dateList;
	private Graph graph;
	private Calendar startDate;
	private Calendar endDate;
	private JButton forward;
	private JButton back;
	private JTextField entry;
	private JTabbedPane atNumberPane;
	private JToolBar toolBar;
	private int lastIndex;
	private int lastAtNumber;
	private static final String atNumberString= "Average Time At Number";
	private static final int AVERAGE_TIME= 0;
	private static final int FAST_TIME= 1;
	private static final int PERCENTAGE_CORRECT= 2;
	private static final int PERCENTAGE_CORRECT_ON_FIRST= 3;
	
	
	public GraphPane(DateList dateList)
	{
		this.dateList= dateList;
		atNumberPane= new JTabbedPane();
		addTab("Average Time", createPanel(AVERAGE_TIME, false));
		addTab("Fastest Time", createPanel(FAST_TIME,false));
		addTab("Percentage Correct", createPanel(PERCENTAGE_CORRECT, false));
		addTab("Percentage Correct On First Try",
				createPanel(PERCENTAGE_CORRECT_ON_FIRST,false));
		addTab(atNumberString, atNumberPane);
		int max= 0;
		for(DateList.DateNode k : dateList.getList())
		{
			int next= k.getList().getBaseStats().getCorrectAtNumber().getSize();
			if(next>max)
			{
				max= next; 
			}
		}
		if(max==0) return;
		for(int k=0; k<max; k++)
		{
			atNumberPane.addTab("At: "+(k+1), createPanel(k+1, true));
		}
		endDate= Calendar.getInstance();
		startDate= Calendar.getInstance();
		Calendar lastDate= dateList.getList().get(dateList.getList().size()-1).getDate();
		endDate.setTimeInMillis(lastDate.getTimeInMillis());
		startDate.setTimeInMillis(lastDate.getTimeInMillis());
		for(int k=0; k<10; k++)
		{
			Global.rollDate(startDate, false);
		}
		toolBar= new JToolBar();
		toolBar.setFloatable(false);
		toolBar.setRollover(true);
		forward= new JButton("Forward");
		forward.setMnemonic(KeyEvent.VK_F);
		back= new JButton("Back");
		back.setMnemonic(KeyEvent.VK_B);
		if(forward.getActionListeners().length==0)
		{
			forward.addActionListener(this);
			back.addActionListener(this);
		}
		JLabel go= new JLabel("Go");
		JLabel days= new JLabel("Days");
		entry= new JTextField("1", 3);
		toolBar.setLayout(new FlowLayout());
		toolBar.add(go);
		toolBar.add(entry);
		toolBar.add(days);
		toolBar.add(forward);
		toolBar.add(back);
		lastIndex= getSelectedIndex();
		((JComponent)(getSelectedComponent()))
		  .add(toolBar, BorderLayout.PAGE_START);
		addChangeListener(this);
		atNumberPane.addChangeListener(this);
	}
	
    private JPanel createPanel(int type, boolean graphOfAvgTimeAtNum)
    {
    	JPanel panel= new JPanel();
    	panel.setLayout(new BorderLayout());
    	panel.add(new GraphPanel(type, graphOfAvgTimeAtNum),BorderLayout.CENTER);
    	return panel;
    }
	
	
	@Override
	public void actionPerformed(ActionEvent e) 
	{
		int days= 0;
		
		try
		{
			days= Integer.parseInt(entry.getText());
		}
		catch(NumberFormatException ex)
		{
			return;
		}
		if(days<=0) return;
		if(e.getActionCommand()==forward.getActionCommand())
		{
			if(endDate.after(
					   dateList.getList().get(dateList.getList().size()-1).getDate())||
					   Global.sameDate(endDate, 
					   dateList.getList().get(dateList.getList().size()-1).getDate()))
			{
				return;
			}
			for(int k=0; k<days; k++)
			{
				Global.rollDate(endDate, true);
				Global.rollDate(startDate, true);
				if(endDate.after(
				   dateList.getList().get(dateList.getList().size()-1).getDate())||
				   Global.sameDate(endDate, 
				   dateList.getList().get(dateList.getList().size()-1).getDate()))
				{
					getSelectedComponent().repaint();
					return;
				}
			}
		}
		if(e.getActionCommand()==back.getActionCommand())
		{
			if(startDate.before(dateList.getList().get(0).getDate())||
			     Global.sameDate(startDate, dateList.getList().get(0).getDate()))
			{
				return;
			}
			for(int k=0; k<days; k++)
			{
				Global.rollDate(startDate, false);
				Global.rollDate(endDate, false);
				if(startDate.before(dateList.getList().get(0).getDate())||
				   Global.sameDate(startDate, dateList.getList().get(0).getDate()))
				{
					getSelectedComponent().repaint();
					return;
				}
			}
		}
		getSelectedComponent().repaint();
	}


	@Override
	public void stateChanged(ChangeEvent e) 
	{
		if(lastIndex==indexOfTab(atNumberString))
		{
			((JComponent)atNumberPane.getComponent(lastAtNumber)).remove(toolBar);
		}
		else ((JComponent)getComponent(lastIndex)).remove(toolBar);
		if(getSelectedIndex()==indexOfTab(atNumberString))
		{
			((JComponent)(atNumberPane.getSelectedComponent()))
			  .add(toolBar, BorderLayout.PAGE_START);
		}
		else ((JComponent)(getSelectedComponent()))
		  .add(toolBar, BorderLayout.PAGE_START);
		lastIndex= getSelectedIndex();
	}


	private class GraphPanel extends JPanel
	{
		int type;
		boolean graphOfAvgTimeAtNum;
		
		private GraphPanel(int type, boolean graphOfAvgTimeAtNum)
		{
			this.type= type;
			this.graphOfAvgTimeAtNum= graphOfAvgTimeAtNum;
		}
	
		@Override 
		public void paintComponent(Graphics g)
		{
			super.paintComponent(g);
			graph= new Graph(0, getWidth(), 0, getHeight(), dateList, startDate, endDate);
			if(graphOfAvgTimeAtNum)
			{
				graph.graphAverageTimeAtNumber(g, type);
			}
			else switch(type)
			{
				case AVERAGE_TIME:
					graph.graphAverageTimes(g);
					return;
					
				case FAST_TIME:
					graph.graphFastestTimes(g);
					return;
					
				case PERCENTAGE_CORRECT:
					graph.graphPercentageCorrect(g);
					return;
					
				case PERCENTAGE_CORRECT_ON_FIRST:
					graph.graphPercentageCorrectOnFirstTry(g);
					return;
			}
		}
	}
	
	
}
